﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using Silvermoon.Controls;
using Microsoft.WindowsMobile.PocketOutlook;
using Silvermoon.Images;
using OutlookHub.Images;
using OutlookHub.Styles;
using OutlookHub.Controls;
using OutlookHub.Utils;
using Silvermoon.UI;
using Silvermoon.Controls.Forms;
using OutlookHub.Models;
using Silvermoon.Navigation;

namespace OutlookHub.Pages
{
    public class TasksPage : Page
    {
        private ContextMenu itemMenu;
        private IEnumerable<Task> tasks;
        private ListViewController<TaskItem, Task> allTasksController, activeTasksController, completedTasksController, todayTasksController;
        private ListView allTasksLv, activeTasksLv, completedTasksLv, todayTasksLv;
        private TabPage allTasksTab, activeTasksTab, completedTasksTab, todayTasksTab;
        private TabControl tabs;
        private OutlookSession session;


        public TasksPage()
            : base()
        {
            session = OutlookContext.Context.Session;
            InitializePage();
        }

        protected override void Dispose(bool dispose)
        {
            DisposeObject(itemMenu);
            base.Dispose(dispose);
        }

        private void InitializePage()
        {
            SetTransition(350, TransitionMask.RotateLeftIn, TransitionMask.RotateLeftIn);
            Styles = StylePool.Details;

            string filter = Context.CategoriesFilter;
            Title = "TASKS" + (string.IsNullOrEmpty(filter) ? "" : ": " + filter.ToUpper());

            todayTasksLv = new ListView { Margin = Margin.Zero };
            allTasksLv = new ListView { Margin = Margin.Zero };
            activeTasksLv = new ListView { Margin = Margin.Zero };
            completedTasksLv = new ListView { Margin = Margin.Zero };
            allTasksTab = new TabPage("all", allTasksLv);
            activeTasksTab = new TabPage("active", activeTasksLv);
            completedTasksTab = new TabPage("completed", completedTasksLv);
            todayTasksTab = new TabPage("today", todayTasksLv);
            tabs = new TabControl();
            tabs.SetPages(todayTasksTab, activeTasksTab, completedTasksTab, allTasksTab);

            itemMenu = new ContextMenu();
            itemMenu.AddItem("Delete Task").Tap += new EventHandler<TapEventArgs>(OnDeleteTask);
            itemMenu.AddItem("Edit Task").Tap += new EventHandler<TapEventArgs>(OnEditTask);

            Controls.Add(tabs);
            CreateControllers();

            Toolbar tb = new Toolbar();
            tb.AddButton(SysImages.Add).Tap += new EventHandler<TapEventArgs>(OnAddTask);
            tb.AddButton(ImagePool.SortOrder).Tap += new EventHandler<TapEventArgs>(OnSort);
            tb.AddButton(ImagePool.Filter).Tap += new EventHandler<TapEventArgs>(OnFilter);
            Toolbar = tb;

            LoadData();
        }

        public OutlookContext Context
        {
            get { return OutlookContext.Context; }
        }

        void OnFilter(object sender, TapEventArgs e)
        {
            CategoriesPage page = new CategoriesPage();
            page.SelectedCategories = Context.SelectedCategories;
            page.Selected += (s, ee) =>
                {
                    Context.SelectedCategories = page.SelectedCategories;
                };

            this.NavigateTo(page);
        }


        void OnSort(object sender, TapEventArgs e)
        {
            TaskSortOrderPage page = new TaskSortOrderPage();
            page.Selected += new EventHandler<TaskSortOrderPage.TaskOrderEventArgs>(page_Selected);
            NavigateTo(page);
        }

        static void page_Selected(object sender, TaskSortOrderPage.TaskOrderEventArgs e)
        {
            OutlookContext.Context.TaskOrder = e.TaskOrder;
        }

        void OnAddTask(object sender, TapEventArgs e)
        {
            Task task = new Task();
            task.ReminderSet = false;
            task.Categories = OutlookContext.Context.CategoriesFilter;
            OnEditTask(task, true);
        }

        void OnEditTask(object sender, TapEventArgs e)
        {
            Item item = itemMenu.AnchorControl as Item;
            Task task = item != null ? item.DataValue as Task : null;
            OnEditTask(task, false);
        }

        private void OnEditTask(Task task, bool isNew)
        {
            if (task != null)
            {
                EditTaskDetailsPage page = new EditTaskDetailsPage { IsDetailsParent = true };
                if (isNew)
                {
                    page.Task = task;
                    page.Title = "NEW TASK";
                    page.Accept += new EventHandler<OutlookHub.Classes.TaskEventArgs>(OnAcceptNewTask);
                    page.IsDeleteEnabled = false;
                }
                else
                {
                    Task copy = new Task();
                    copy.Copy(task);
                    page.Task = copy;
                    page.Accept += (s, e) =>
                        {
                            task.Copy(e.Task);
                            task.Update();
                        };
                }
                this.NavigateTo(page);
            }
        }


        private static void OnAcceptNewTask(object sender, OutlookHub.Classes.TaskEventArgs e)
        {
            OutlookContext.Context.Session.Tasks.Items.Add(e.Task);
            e.Task.Update();
        }

        void OnDeleteTask(object sender, TapEventArgs e)
        {
            Item item = itemMenu.AnchorControl as Item;
            Task task = item != null ? item.DataValue as Task : null;
            if (task != null)
            {
                MessageDialog.Show("DELETE TASK", "Delete task " + task.Subject + "?", "Delete", "Cancel", () => DeleteTask(task), null);
            }
        }

        private void DeleteTask(Task task)
        {
            itemMenu.UndoAnchor(false);
            todayTasksController.RemoveValue(task);
            allTasksController.RemoveValue(task);
            activeTasksController.RemoveValue(task);
            completedTasksController.RemoveValue(task);
            task.Delete();
        }

        private void LoadData()
        {
            tasks = Context.AllTasks.ToArray();
            todayTasksController.DataSource = GetTodayTasks(tasks);
            activeTasksController.DataSource = Filtered(tasks.Where(t => !t.Complete));
            completedTasksController.DataSource = Filtered(tasks.Where(t => t.Complete));
            allTasksController.DataSource = Filtered(tasks);
        }

        private List<Task> GetTodayTasks(IEnumerable<Task> tasks)
        {
            DateTime now = DateTime.Now.Date;
            return Filtered(tasks.Where(t => !t.Complete && ((t.StartDate.IsNull() || t.StartDate <= now) || (t.StartDate.IsNull() || t.DueDate <= now))));
        }

        private List<Task> Filtered(IEnumerable<Task> tasks)
        {
            string filter = Context.CategoriesFilter;
            if (!string.IsNullOrEmpty(filter)) tasks = tasks.Where(c => ContainsCategory(c, Context));
            tasks = OrderTasks(tasks);
            return tasks.ToList();
        }

        private IEnumerable<Task> OrderTasks(IEnumerable<Task> tasks)
        {
            switch (Context.TaskOrder)
            {
                case TaskOrder.DueDate: return tasks.OrderBy(t => t.DueDate);
                case TaskOrder.StartDate: return tasks.OrderBy(t => t.StartDate);
                case TaskOrder.Subject: return tasks.OrderBy(t => t.Subject).ThenBy(t => t.DueDate);
                case TaskOrder.Priority: return tasks.OrderByDescending(t => (int)t.Importance).ThenBy(t => t.DueDate);
                default: throw new NotImplementedException();
            }
        }

        private bool ContainsCategory(Task task, OutlookContext context)
        {
            var categories = task.Categories.SplitByComma();
            return categories.Any(c => context.IsCategoryInFilter(c));
        }

        private void CreateControllers()
        {
            todayTasksController = CreateControllers(todayTasksLv);
            activeTasksController = CreateControllers(activeTasksLv);
            completedTasksController = CreateControllers(completedTasksLv);
            allTasksController = CreateControllers(allTasksLv);
        }

        private ListViewController<TaskItem, Task> CreateControllers(ListView listView)
        {
            listView.TapItem += new EventHandler<ItemEventArgs>(OnTapItem);
            listView.Multiselect = true;
            var controller = new ListViewController<TaskItem, Task>(listView);
            controller.InitializeItem += new EventHandler<ItemControlGeneratorEventArgs<TaskItem>>(controller_InitializeItem);
            return controller;
        }

        void controller_InitializeItem(object sender, ItemControlGeneratorEventArgs<TaskItem> e)
        {
            e.Item.ContextMenu = itemMenu;
        }

        private void OnTapItem(object sender, ItemEventArgs e)
        {
            TaskItem item = e.Item as TaskItem;
            if (item == null) throw new ArgumentNullException("Item");
            Task task = item.DataValue as Task;
            if (item == null) throw new ArgumentNullException("DataValue");

            TaskDetailsPage page = new TaskDetailsPage();
            page.Task = task;
            this.NavigateTo(page);
        }

        protected override void OnCommand(CommandEventArgs args)
        {
            if (args.Command == TaskItem.TaskCompleteCommand) OnTaskCompleteChanged(args.Owner as TaskItem);
            base.OnCommand(args);
        }

        private void OnTaskCompleteChanged(TaskItem taskItem)
        {
            Task task = taskItem.DataValue as Task;
            if (task.Complete)
            {
                todayTasksController.RemoveValue(task);
                activeTasksController.RemoveValue(task);
                completedTasksController.DataSource = Filtered(tasks.Where(t => t.Complete));
            }
            else
            {
                completedTasksController.RemoveValue(task);
                activeTasksController.DataSource = Filtered(tasks.Where(t => !t.Complete));
                todayTasksController.DataSource = GetTodayTasks(tasks);
            }
        }

        private class Bag
        {
            public int PageIndex;
            public int AllY, CompY, ActiveY;
        }

        public override object OnSaveViewState()
        {
            Bag bag = new Bag { PageIndex = tabs.SelectedIndex, AllY = allTasksLv.YOffset, ActiveY = activeTasksLv.YOffset, CompY = completedTasksLv.YOffset };
            return bag;
        }

        public override void OnLoadViewState(object viewState)
        {
            Bag bag = viewState as Bag;
            if (bag != null)
            {
                tabs.SelectedIndex = bag.PageIndex;
                allTasksLv.YOffset = bag.AllY;
                this.activeTasksLv.YOffset = bag.ActiveY;
                this.completedTasksLv.YOffset = bag.CompY;
            }
        }
    }
}
